package Other;

import IceAssembly.Check;
import IceAssembly.Table;
import IceAssembly.Convert;
import IceAssembly.Control;

/**
 * This class will process Reset directive.<p>
 * Creation Date : May 9,2008.<br>
 * <p><b>Original Author:</b>  yogesh
 */
public class Reset {
    Check check_instance = new Check();
    Table table_instance = new Table();
    Convert convert_instance = new Convert();
    
    
    /**
     * 
     */
    public Reset() {
    }
    
    /**
    * This function is called whenever one of the possibilities of reset operand is a number.<p>
    * Modified Log: None.<br>
    * Error Condition tested: None.<br>
    * Creation Date : May 9,2008.<br>
    * Original Author: Yogesh Jindal.<br>
    * <p><b>Original Author:</b>  Yogesh Jindal
    * @param operand - operand to be processed as an integer.
    * @return Returns 0 if the operand is not an integer.<br>
    *         Returns 50 to proceed to next line.<br>
    *         Returns 1000 if error table out of range.<br> 
    */
    private int processOne(String label ,String operand){
        if(check_instance.isInt(operand)!=1){
            return 0;
        }
        int temp=0;
        try{
            temp = Integer.parseInt(operand);
            if(temp>1023 || temp<Control.location_counter){
                return 0;
            }
        }catch(Exception e){
            return 0;
        }
        if(table_instance.addToSymbolTable(label,"RESET","-")==0){
            if(table_instance.addToErrorTable("164")==0){//more than 50 labels.
                return 1000;//fatal error more than 3072 errors
            }
            return 50;
        }
        Control.location_counter = temp;
        return 50;        
    }
    
    /**
    * This function is called whenever one of the possibilities of reset operand is Star notation.<p>
    * Modified Log: None.<br>
    * Error Condition tested: None.<br>
    * Creation Date : May 9,2008.<br>
    * Original Author: Yogesh Jindal.<br>
    * <p><b>Original Author:</b>  Yogesh Jindal
    * @param operand - operand to be processed as an integer.
    * @return Returns 0 if the operand is not a valid star notation.<br>
    *         Returns 50 to proceed to next line.<br>
    *         Returns 1000 if error table out of range.<br> 
    */
    private int processThree(String label ,String operand){
        if(operand.length()<3){
            return 0;
        }
        if(!operand.substring(0,2).contentEquals("*+")){
            return 0;
        }
        operand = operand.substring(2);
        
        if(check_instance.isInt(operand)==1){
            try{
                int offset = Integer.parseInt(operand);
                if(offset+Control.location_counter>1023){
                    return 0;
                }
            Control.location_counter = Integer.parseInt(operand)+Control.location_counter;
            }catch(Exception e){
                return 0;
            }
        }else{
            if(check_instance.isValidLabel(operand)!=2){
                return 0;
            }else{
                int temp = Integer.parseInt(table_instance.getLcOfLabel(operand),16);
                if(temp+Control.location_counter>1023){
                    return 0;
                }else{
                    Control.location_counter=temp+Control.location_counter;
                }
            }
        }
        
        if(table_instance.addToSymbolTable(label,"RESET","-")==0){
            if(table_instance.addToErrorTable("164")==0){//more than 50 labels.
                return 1000;//fatal error more than 3072 errors
            }
            return 50;
        }
        return 50;
    }
    
    /**
    * This function is called whenever one of the possibilities of reset operand is an expression.<p>
    * Modified Log: None.<br>
    * Error Condition tested: None.<br>
    * Creation Date : May 12,2008.<br>
    * Original Author: Yogesh Jindal.<br>
    * <p><b>Original Author:</b>  Yogesh Jindal
    * @param operand - operand to be processed as an Expression.
    * @return Returns 0 if the operand is not a Reset type expression.<br>
    *         Returns 50 to proceed to next line.<br>
    *         Returns 1000 if error table out of range.<br> 
    */
    private int processFour(String label ,String operand){
        if(operand.length()<4){
            return 0;
        }
        if(!(operand.contains("+")||operand.contains("-"))){
            return 0;
        }        
        if(operand.contains("+")&&operand.contains("-")){
            return 0;
        }
        if(operand.substring(0,1).contentEquals("+")||operand.substring(0,1).contentEquals("-")){
            return 0;
        }
        String op1,op2;
        if(operand.contains("+")){
            int first_plus_index = operand.indexOf("+");
            op1 = operand.substring(0, first_plus_index);
            op2 = operand.substring(first_plus_index+1);            
        }else{
            int first_minus_index = operand.indexOf("-");
            op1 = operand.substring(0, first_minus_index);
            op2 = operand.substring(first_minus_index+1);
        }
        if(op1.contentEquals("")||op2.contentEquals("")){
            return 0;
        }
        if(!(check_instance.isValidLabel(op1)==2&&check_instance.isValidLabel(op2)==2)){
            return 0;
        }
        
        int temp1 = Integer.parseInt(table_instance.getLcOfLabel(op1),16);
        int temp2 = Integer.parseInt(table_instance.getLcOfLabel(op2),16);
        int temp= temp1+temp2;
        if(temp<Control.location_counter || temp>1023){
            if(table_instance.addToErrorTable("163")==0){
                return 1000;//fatal error more than 3072 errors
            }
            return 50;
        }else{
            Control.location_counter = temp;
        }
        
        if(table_instance.addToSymbolTable(label,"RESET","-")==0){
            if(table_instance.addToErrorTable("164")==0){//more than 50 labels.
                return 1000;//fatal error more than 3072 errors
            }
            return 50;
        }        
        return 50;        
    }
    
    /**
    * This function is called whenever one of the possibilities of reset operand is an expression like 
    * number(+or-)number.<p>
    * Modified Log: None.<br>
    * Error Condition tested: None.<br>
    * Creation Date : May 12,2008.<br>
    * Original Author: Yogesh Jindal.<br>
    * <p><b>Original Author:</b>  Yogesh Jindal
    * @param operand - operand to be processed as an Expression.
    * @return Returns 0 if the operand is not a Reset type expression.<br>
    *         Returns 50 to proceed to next line.<br>
    *         Returns 1000 if error table out of range.<br> 
    */
    private int processFive(String label ,String operand){
        if(operand.length()<4){
            return 0;
        }
        if(!(operand.contains("+")||operand.contains("-"))){
            return 0;
        }        
        if(operand.contains("+")&&operand.contains("-")){
            return 0;
        }
        if(operand.substring(0,1).contentEquals("+")||operand.substring(0,1).contentEquals("-")){
            return 0;
        }
        String op1,op2;
        if(operand.contains("+")){
            int first_plus_index = operand.indexOf("+");
            op1 = operand.substring(0, first_plus_index);
            op2 = operand.substring(first_plus_index+1);            
        }else{
            int first_minus_index = operand.indexOf("-");
            op1 = operand.substring(0, first_minus_index);
            op2 = operand.substring(first_minus_index+1);
        }
        if(op1.contentEquals("")||op2.contentEquals("")){
            return 0;
        }
        if(!(check_instance.isInt(op1)==1&&check_instance.isInt(op2)==1)){
            return 0;
        }
        
        int int_op1 = Integer.parseInt(op1);
        int int_op2 = Integer.parseInt(op2);
        int int_op=0;
        if(operand.contains("+")){
            int_op= int_op1+int_op2;
        }else{
            int_op= int_op1-int_op2;
        }        
        if(int_op<Control.location_counter || int_op>1023){           
            return 0;
        }
        Control.location_counter = int_op;        
        if(table_instance.addToSymbolTable(label,"RESET","-")==0){
            if(table_instance.addToErrorTable("164")==0){//more than 50 labels.
                return 1000;//fatal error more than 3072 errors
            }
            return 50;
        }        
        return 50;        
    }
    
    /**
    * This function is called whenever one of the possibilities of reset operand is an expression like 
    * number(+or-)label or label(+or-)number.<p>
    * Modified Log: None.<br>
    * Error Condition tested: None.<br>
    * Creation Date : May 12,2008.<br>
    * Original Author: Yogesh Jindal.<br>
    * <p><b>Original Author:</b>  Yogesh Jindal
    * @param operand - operand to be processed as an Expression.
    * @return Returns 0 if the operand is not a Reset type expression.<br>
    *         Returns 50 to proceed to next line.<br>
    *         Returns 1000 if error table out of range.<br> 
    */
    private int processSix(String label ,String operand){
        if(operand.length()<4){
            return 0;
        }
        if(!(operand.contains("+")||operand.contains("-"))){
            return 0;
        }        
        if(operand.contains("+")&&operand.contains("-")){
            return 0;
        }
        if(operand.substring(0,1).contentEquals("+")||operand.substring(0,1).contentEquals("-")){
            return 0;
        }
        String op1,op2;
        if(operand.contains("+")){
            int first_plus_index = operand.indexOf("+");
            op1 = operand.substring(0, first_plus_index);
            op2 = operand.substring(first_plus_index+1);            
        }else{
            int first_minus_index = operand.indexOf("-");
            op1 = operand.substring(0, first_minus_index);
            op2 = operand.substring(first_minus_index+1);
        }
        if(op1.contentEquals("")||op2.contentEquals("")){
            return 0;
        }        
        int int_op1;
        int int_op2;
        if(check_instance.isInt(op1)==1 && check_instance.isValidLabel(op2)==2){
            try{
                int_op1 = Integer.parseInt(op1);
                if(int_op1>1023){
                    return 0;
                }
                String[] all_exvar = table_instance.getAllLabels("Exvar");
                if(!all_exvar[0].contentEquals("0")){
                    for(int index=1; index<all_exvar.length; index++){
                        if(op2.contentEquals(all_exvar[index])){
                            return 0;
                        }
                    }
                }
                int_op2 = Integer.parseInt(table_instance.getLcOfLabel(op2),16);
            }catch(Exception e){
                return 0;
            }        
        }else if(check_instance.isValidLabel(op1)==2 && check_instance.isInt(op2)==1){
            try{
                int_op2 = Integer.parseInt(op2);
                if(int_op2>1023){
                    return 0;
                }
                String[] all_exvar = table_instance.getAllLabels("Exvar");
                if(!all_exvar[0].contentEquals("0")){
                    for(int index=1; index<all_exvar.length; index++){
                        if(op1.contentEquals(all_exvar[index])){
                            return 0;
                        }
                    }
                }
                int_op1 = Integer.parseInt(table_instance.getLcOfLabel(op1),16);
            }catch(Exception e){
                return 0;
            }        
        }else{
            return 0;
        }
        int op_value;
        if(operand.contains("+")){
            op_value = int_op1+int_op2;
        }else{
            op_value = int_op1-int_op2;
        }
        if(op_value<Control.location_counter || op_value>1023){
            return 0;
        }        
        Control.location_counter = op_value;
        if(table_instance.addToSymbolTable(label,"RESET","-")==0){
            if(table_instance.addToErrorTable("164")==0){//more than 50 labels.
                return 1000;//fatal error more than 3072 errors
            }
            return 50;
        }        
        return 50;        
    }
    
    /**
    * This function is called whenever one of the possibilities of reset operand is label.
    * The label can be an equated label, or a simple label or an external label.<p>
    * Modified Log: None.<br>
    * Error Condition tested: None.<br>
    * Creation Date : May 9,2008.<br>
    * Original Author: Yogesh Jindal.<br>
    * <p><b>Original Author:</b>  Yogesh Jindal
    * @param operand - operand to be processed as an integer.
    * @return Returns 0 if the operand is not a label.<br>
    *         Returns 50 to proceed to next line.<br>
    *         Returns 1000 if error table out of range.<br> 
    */
    private int processTwo(String label ,String operand){
        if(check_instance.isValidLabel(operand)==0){
            return 0;
        }
        
        IceAssembly.Table table_instance = new IceAssembly.Table();
        String[] equ_labels = table_instance.getAllLabels("EQU");
        if(equ_labels[0].contentEquals("0")){
            return 0;
        }else{
            for(int index=1; index<equ_labels.length; index++){
                if(equ_labels[index].contentEquals(operand)){
                    String equ_value_string = table_instance.getEquValueOfLabel(equ_labels[index]);
                    int equ_value_int = Integer.parseInt(equ_value_string, 16);
                    if(Control.location_counter>equ_value_int){
                        return 0;
                    }else{
                       Control.location_counter = equ_value_int;
                    }
                }
            }
        }
        //initialize_instance.
        /*if(table_instance.addToErrorTable("163")==0){
            return 1000;//fatal error more than 3072 errors
        }*/
        if(table_instance.addToSymbolTable(label,"RESET","-")==0){
            if(table_instance.addToErrorTable("164")==0){//more than 50 labels.
                return 1000;//fatal error more than 3072 errors
            }
            return 50;
        }
        return 50;
    }
    
    /**
     * This is the main driving function of this class. This function checks the different possibilities
     * for reset operand by calling process fuctions.
     * Modified Log: None.<br>
     * Error Condition tested: None.<br>
     * Creation Date : May 9,2008.<br>
     * Original Author: Yogesh Jindal.<br>
     * @param label The label for reset directive.
     * @param operand The operand for reset directive.
     * @return
     */
    public int processReset(String label, String operand){
        if(operand.contentEquals("")){//no operands.
            if(table_instance.addToErrorTable("163")==0){
                return 1000;//fatal error more than 3072 errors
            }
            return 50;
        }
        operand = operand.replace(" *", "*"); operand = operand.replace("* ", "*");
        operand = operand.replace(" +", "+"); operand = operand.replace("+ ", "+");
        operand = operand.replace(" -", "-"); operand = operand.replace("- ", "-");
        operand = operand.replace(" /", "/"); operand = operand.replace("/ ", "/");
                
        int ret_value;
        ret_value = processOne(label,operand);
        if(ret_value!=0){
            return 0;
        }
        ret_value = processTwo(label,operand);
        if(ret_value!=0){
            return 0;
        }
        ret_value = processThree(label,operand);
        if(ret_value!=0){
            return 0;
        }
        ret_value = processFour(label,operand);
        if(ret_value!=0){
            return 0;
        }
        ret_value = processFive(label,operand);
        if(ret_value!=0){
            return 0;
        }
        ret_value = processSix(label,operand);
        if(ret_value!=0){
            return 0;
        }
        if(table_instance.addToErrorTable("163")==0){
            return 1000;//fatal error more than 3072 errors
        }
        return 50;
    }
}
